package com.mk.sso.controller;

import com.alibaba.fastjson.JSON;
import com.mk.sso.dto.RefreshTokenDTO;
import com.mk.sso.dto.UserDTO;
import com.mk.sso.entity.User;
import com.mk.sso.properties.SsoServerProperties;
import com.mk.sso.sdk.beans.SsoUser;
import com.mk.sso.sdk.conf.SsoConf;
import com.mk.sso.sdk.result.ResultEnum;
import com.mk.sso.sdk.result.ReturnT;
import com.mk.sso.sdk.util.JedisUtil;
import com.mk.sso.sdk.util.JwtUtil;
import com.mk.sso.sdk.util.SsoTokenLoginHelper;
import com.mk.sso.service.UserService;
import com.mk.sso.vo.TokenVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import java.util.UUID;

@Api(tags = "APP客户端登录相关接口")
@RestController
@RequestMapping("/oauth")
public class AppController {

    @Autowired
    private SsoServerProperties properties;

    @Autowired
    private UserService userService;


    /**
    * 描述:app客户端登录
    * @author maming
    * @date 2021/11/12
    * @param userDTO
    * @return {@link ReturnT}
    */
    @ApiOperation("APP客户端登录接口")
    @PostMapping("/login")
    public ReturnT login(@Validated @RequestBody UserDTO userDTO){

        User user = userService.getByUserNameAndPassword(userDTO.getUsername(), userDTO.getPassword());

        if (!ObjectUtils.isEmpty(user)) {
            SsoUser ssoUser = SsoUser.builder()
                    .userId(String.valueOf(user.getId()))
                    .userName(user.getUserName())
                    .build();

            String subject = JSON.toJSONString(ssoUser);

            String token = JwtUtil.generateToken(properties.getIssuser(),
                    subject,
                    properties.getSecretKey(),
                    properties.getMaxAge());

            // 将用户信息存储到缓存
            SsoTokenLoginHelper.storageUser(token, ssoUser, properties.getMaxAge());

            // 生成refreshToken并保存
            String refreshToken = UUID.randomUUID().toString().replace("-","");
            JedisUtil.setStringValue(SsoConf.REFRESH_TOKEN_PREFIX + refreshToken, token, SsoConf.REFRESH_TOKEN_MAXAGE);

            TokenVo tokenVo = TokenVo.builder()
                    .token(token)
                    .refreshToken(refreshToken)
                    .build();

            return ReturnT.success(tokenVo);
        }

        return ReturnT.failure(SsoConf.AUTH_FAILE_WARN);
    }


    /**
    * 描述:app客户端退出
    * @author maming
    * @date 2021/11/12
    * @param token
    * @return {@link ReturnT}
    */
    @ApiOperation("APP客户端注销接口")
    @ApiImplicitParam(name = "accessToken", required = true, type = "header")
    @GetMapping("/logout")
    public ReturnT logout(@RequestHeader(SsoConf.TOKEN_AUTH_HEADER) String token){
        // 根据token删除缓存中的某个用户信息
        SsoTokenLoginHelper.removeStorageUser(token);

        return ReturnT.success();
    }

    /**
    * 描述:根据refreshToken生成新的token
    * @author maming
    * @date 2021/11/23
    * @param refreshTokenDTO
    * @return {@link ReturnT}
    */
    @ApiOperation("APP客户端刷新token接口")
    @PostMapping("/refreshToken")
    public ReturnT refreshToken(@RequestBody @Validated RefreshTokenDTO refreshTokenDTO){
        String refreshToken = refreshTokenDTO.getRefreshToken();

        String token = JedisUtil.getStringValue(SsoConf.REFRESH_TOKEN_PREFIX + refreshToken);

        if (StringUtils.isEmpty(token)) {
            return ReturnT.failure(ResultEnum.REFRESH_TOKEN_ERROR);
        }

        // 获取当前登录用户信息
        SsoUser ssoUser = SsoTokenLoginHelper.getStorageUser(token);
        // 清除旧token
        SsoTokenLoginHelper.removeStorageUser(token);

        String subject = JSON.toJSONString(ssoUser);
        // 生成新token
        String newToken = JwtUtil.generateToken(properties.getIssuser(),
                subject,
                properties.getSecretKey(),
                properties.getMaxAge());

        // 将用户信息存储到缓存
        SsoTokenLoginHelper.storageUser(newToken, ssoUser, properties.getMaxAge());
        // 绑定新的token
        JedisUtil.setStringValue(SsoConf.REFRESH_TOKEN_PREFIX + refreshToken, newToken, SsoConf.REFRESH_TOKEN_MAXAGE);

        return ReturnT.success(newToken);
    }
}
